﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.IO;
using System.ComponentModel;
using System.Web;
using System.Web.UI;

namespace UOL.PagSeguro {

    [AspNetHostingPermission(System.Security.Permissions.SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
    [DefaultEvent("VendaEfetuada")]
    [DefaultProperty("Token")]
    [Description("Processa o retorno automático de uma venda através do UOL PagSeguro")]
    [Designer(typeof(Design.RetornoPagSeguroDesigner))]
    public class RetornoPagSeguro : Control {

        private static readonly string ENCODING = "iso-8859-1";

        public delegate void VendaEfetuadaEventHandler(RetornoVenda retornoVenda);
        public event VendaEfetuadaEventHandler VendaEfetuada;

        public event EventHandler<VendaAutenticadaEventArgs> RetornoVerificado;
        public event EventHandler<VendaNaoAutenticadaEventArgs> VendaNaoAutenticada;
        public event EventHandler<FalhaProcessarRetornoEventArgs> FalhaProcessarRetorno;

        private string _urlNPI;
        private string _token;

        /// <summary>
        /// Token de Segurança
        /// </summary>
        public string Token {
            get {
                return _token;
            }
            set {
                _token = value;
            }
        }

        /// <summary>
        /// URL do Serviço de NPI do PagSeguro
        /// </summary>
        public string UrlNPI {
            get {
                return _urlNPI;
            }
            set {
                _urlNPI = value;
            }
        }

        public RetornoPagSeguro() {
            this._urlNPI = Resources.PagSeguro_NPI;
        }

        public RetornoPagSeguro(string token)
            : this() {
            this._token = token;
        }

        protected override void OnLoad(EventArgs e) {
            if (this.Page != null) {
                this.ProcessarRetorno(this.Page.Request);
            }
        }

        public void ProcessarRetorno() {
            this.ProcessarRetorno(null);
        }

        public void ProcessarRetorno(HttpRequest request) {
            if (request == null) {
                request = HttpContext.Current.Request;
            }

            if (request.Form.Count > 0) {
                try {
                    request.ContentEncoding = Encoding.GetEncoding(RetornoPagSeguro.ENCODING);

                    string requestContent = HttpUtility.UrlDecode(request.Form.ToString(), request.ContentEncoding) + "&Comando=validar&Token=" + this._token;
                    HttpWebRequest NPIRequest = (HttpWebRequest)WebRequest.Create(this._urlNPI);
                    NPIRequest.Method = WebRequestMethods.Http.Post;
                    NPIRequest.ContentType = "application/x-www-form-urlencoded";
                    NPIRequest.ContentLength = requestContent.Length;

                    StreamWriter writer = new StreamWriter(NPIRequest.GetRequestStream(), request.ContentEncoding);
                    writer.Write(requestContent);
                    writer.Close();

                    StreamReader reader = new StreamReader(NPIRequest.GetResponse().GetResponseStream(), request.ContentEncoding);
                    string NPIResponse = reader.ReadToEnd();
                    reader.Close();

                    if ("VERIFICADO".Equals(NPIResponse, StringComparison.InvariantCultureIgnoreCase) && this.VendaEfetuada != null) {
                        if (this.RetornoVerificado != null) {
                            this.RetornoVerificado(this, new VendaAutenticadaEventArgs() { NPIRequest = requestContent });
                        }
                        this.VendaEfetuada(RetornoVenda.CriarViaRespostaNPI(request.Form));
                    } else {
                        if (this.VendaNaoAutenticada != null) {
                            this.VendaNaoAutenticada(this, new VendaNaoAutenticadaEventArgs() { NPIRequest = requestContent, NPIResponse = NPIResponse });
                        }
                    }
                } catch (Exception ex) {
                    if (this.FalhaProcessarRetorno != null) {
                        this.FalhaProcessarRetorno(this, new FalhaProcessarRetornoEventArgs() { Exception = ex });
                    }
                }
            }
        }
    }

    public abstract class AutenticacaoVendaEventArgs : EventArgs {
        //Dados constantes no Request efetuado
        private string _npiRequest;
        public string NPIRequest {
            get {
                return this._npiRequest;
            }
            set {
                this._npiRequest = value;
            }
        }
    }

    public class VendaAutenticadaEventArgs : AutenticacaoVendaEventArgs {

    }

    public class VendaNaoAutenticadaEventArgs : AutenticacaoVendaEventArgs {
        //Resposta obtida no Request
        private string _npiResponse;
        public string NPIResponse {
            get {
                return this._npiResponse;
            }
            set {
                this._npiResponse = value;
            }
        }
    }

    public class FalhaProcessarRetornoEventArgs : EventArgs {

        //Mensagem em caso de Erro
        private Exception _exception;
        public Exception Exception {
            get {
                return this._exception;
            }
            set {
                this._exception = value;
            }
        }

    }
}
